/*******************************************************************************
 *                                    ZLG
 *                         ----------------------------
 *                         innovating embedded platform
 *
 * Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
 * All rights reserved.
 *
 * Contact information:
 * web site:    https://www.zlg.cn
 *******************************************************************************/
/*******************************************************************************
 * Includes
 ******************************************************************************/
#include "common/hc32f4a0_errno.h"
#include "core/include/hc32f4a0_pwc.h"
#include "core/include/hc32f4a0_tick.h"
#include "core/include/hc32f4a0_regs_aos.h"
#include "driver/timer/hc32f4a0_timer.h"

/*******************************************************************************
 * Code
 ******************************************************************************/
/**
 * \brief 定时器 0 中断使能设置函数
 *
 * \param[in] p_tmr0_x  定时器 0 寄存器
 * \param[in] channel   定时器 0 通道
 * \param[in] is_enable 是否使能
 */
void timer0_int_enable_set(hc32f4a0_tmr0_regs_t *p_tmr0_x,
                           uint8_t               channel,
                           uint8_t               is_enable){
    if ((!IS_VALID_TMR0(p_tmr0_x)) ||
            (!IS_VALID_TMR0_CHANNEL(channel)))  {
        return;
    }

    channel = TMR0_OFFEST(channel);
    MODIFY_REG32(p_tmr0_x->BCONR, (TMR0_BCONR_INTENA << channel),
            ((uint32_t)is_enable << TMR0_BCONR_INTENA_POS) << channel);
}

/**
 * \brief 定时器 0 触发源设置函数
 *
 * \param[in] event 事件
 */
void timer0_trigger_src_set(event_src_t event){
    MODIFY_REG32(HC32F4A0_AOS->TMR0_HTSSR, AOS_TMR0_HTSSR_TRGSEL, (uint32_t)event);
}

/**
 * \brief 定时器 0 标志清除函数
 *
 * \param[in] p_tmr0_x 定时器 0 寄存器
 * \param[in] channel  定时器 0 通道
 *
 * \retval 成功返回 0
 */
int timer0_status_clr(hc32f4a0_tmr0_regs_t* p_tmr0_x, uint8_t channel){
    if ((p_tmr0_x == NULL) ||
            (!IS_VALID_TMR0(p_tmr0_x)) ||
            (!IS_VALID_TMR0_CHANNEL(channel)))  {
        return -EINVAL;
    }

    channel = TMR0_OFFEST(channel);
    /* 清除标志*/
    CLEAR_REG32_BIT(p_tmr0_x->STFLR, (TMR0_STFLR_CMFA << channel));
    return 0;
}

/**
 * \brief 定时器 0 启动
 *
 * \param[in] p_tmr0_x 定时器 0 寄存器
 * \param[in] channel  定时器 0 通道
 *
 * \retval 成功返回 0
 */
int timer0_start(hc32f4a0_tmr0_regs_t *p_tmr0_x,
                 uint8_t               channel){

    if ((p_tmr0_x == NULL) ||
            (!IS_VALID_TMR0(p_tmr0_x)) ||
            (!IS_VALID_TMR0_CHANNEL(channel)))  {
        return -EINVAL;
    }

    channel = TMR0_OFFEST(channel);
    MODIFY_REG32(p_tmr0_x->BCONR, (TMR0_BCONR_CSTA <<channel),
            ((uint32_t)1 << TMR0_BCONR_CSTA_POS) << channel);

    return 0;
}

/**
 * \brief 定时器 0 关闭
 *
 * \param[in] p_tmr0_x 定时器 0 寄存器
 * \param[in] channel  定时器 0 通道
 *
 * \retval 成功返回 0
 */
int timer0_stop(hc32f4a0_tmr0_regs_t *p_tmr0_x,
                uint8_t               channel){

    if ((p_tmr0_x == NULL) ||
            (!IS_VALID_TMR0(p_tmr0_x)) ||
            (!IS_VALID_TMR0_CHANNEL(channel)))  {
        return -EINVAL;
    }

    channel = TMR0_OFFEST(channel);
    MODIFY_REG32(p_tmr0_x->BCONR, (TMR0_BCONR_CSTA <<channel),
            ((uint32_t)0 << TMR0_BCONR_CSTA_POS) << channel);

    return 0;
}

/**
 * \brief 定时器 0 初始化
 *
 * \param[in] p_tmr0_x 定时器 0 寄存器
 * \param[in] channel  定时器 0 通道
 * \param[in] p_cfg    定时器 0 配置
 *
 * \retval 成功返回 0
 */
int timer0_init(hc32f4a0_tmr0_regs_t *p_tmr0_x,
                uint8_t               channel,
                struct timr0_cfg     *p_cfg){
    uint32_t tmp;
    uint32_t cmpr_addr;
    uint32_t cntr_addr;

    if ((p_cfg == NULL) ||
            (!IS_VALID_TMR0(p_tmr0_x)) ||
            (!IS_VALID_TMR0_CHANNEL(channel)) ||
            (!IS_VALID_TMR0_CLK_DIVISION(p_cfg->clock_division)) ||
            (!IS_VALID_TMR0_CLK_SRC(p_cfg->clock_source)) ||
            (!IS_VALID_TMR0_FUNC(p_cfg->tmr0_func)) ||
            (!IS_VALID_TMR0_HWTRG_FUNC(p_cfg->hw_trig_func)))  {
        return -EINVAL;
    }

    tmp                 = (uint32_t)channel * 4;
    cntr_addr           = (uint32_t)(&p_tmr0_x->CNTAR) + tmp;
    cmpr_addr           = (uint32_t)(&p_tmr0_x->CMPAR) + tmp;
    RW_MEM32(cntr_addr) = p_cfg->cnt_value;
    RW_MEM32(cmpr_addr) = p_cfg->cmp_value;

    tmp      = p_cfg->clock_division | p_cfg->hw_trig_func | p_cfg->tmr0_func;
    channel *= TMR0_CHB_POS;

    /* 配置模式，时钟源*/
    MODIFY_REG32(p_tmr0_x->BCONR, (TMR0_BCONR_INIT_MSK << channel), (tmp << channel));
    /* 配置时钟模式*/
    MODIFY_REG32(p_tmr0_x->BCONR, (TMR0_CHA_CLKSRC_MSK << channel), (p_cfg->clock_source << channel));

    return 0;
}

/**
 * \brief 定时器 0 反初始化
 *
 * \param[in] p_tmr0_x 定时器 0 寄存器
 */
void timer0_deinit(hc32f4a0_tmr0_regs_t *p_tmr0_x){
    if ((!IS_VALID_TMR0(p_tmr0_x))) {
        return;
    }

    WRITE_REG32(p_tmr0_x->CMPAR, 0x0000FFFFUL);
    WRITE_REG32(p_tmr0_x->CMPBR, 0x0000FFFFUL);
    WRITE_REG32(p_tmr0_x->CNTAR, 0UL);
    WRITE_REG32(p_tmr0_x->CNTBR, 0UL);
    WRITE_REG32(p_tmr0_x->STFLR, 0UL);
    WRITE_REG32(p_tmr0_x->BCONR, 0UL);
}

///**
// * \brief 定时器0 配置
// *        Period = 1 / (Clock / div) * (Compare Value - 1)
// *
// * \param[in] p_tmr0_x      定时器0 结构体
// * \param[in] channel       定时器0 通道
// * \param[in] clk_src       定时器0 时钟源
// * \param[in] clk_div       定时器0 时钟分频
// * \param[in] cmp_val       定时器0 匹配值
// * \param[in] func          定时器0 功能
// * \param[in] hw_trig_func  定时器0 硬件触发功能
// *
// * \retval 成功返回 0
// */
//int timer0_cfg(hc32f4a0_tmr0_regs_t* p_tmr0_x,
//               uint8_t               channel,
//               uint32_t              clk_src,
//               uint32_t              clk_div,
//               uint16_t              cmp_val,
//               uint32_t              func,
//               uint32_t              hw_trig_func){
//    int ret;
//
//    if ((p_tmr0_x == NULL) ||
//            (!IS_VALID_TMR0(p_tmr0_x)) ||
//            (!IS_VALID_TMR0_CHANNEL(channel)) ||
//            (!IS_VALID_TMR0_CLK_DIVISION(clk_div)) ||
//            (!IS_VALID_TMR0_CLK_SRC(clk_src)) ||
//            (!IS_VALID_TMR0_FUNC(func)) ||
//            (!IS_VALID_TMR0_HWTRG_FUNC(hw_trig_func)))  {
//        return -EINVAL;
//    }
//
//    /* 打开自动运行系统时钟*/
//    pwc_fcg0_periph_clk_set(PWC_FCG0_AOS, PWC_ENABLE);
//    /* 打开定时器0 时钟*/
//    pwc_fcg2_periph_clk_set(PWC_FCG2_TMR0_1, PWC_ENABLE);
//    /* 初始化定时器 0*/
//    ret = timer0_init(p_tmr0_x, channel, clk_src, clk_div, cmp_val, func, hw_trig_func);
//    if (ret != 0) {
//        return ret;
//    }
//    /* 等待至少3个异步时钟周期*/
//    delay_ms(1);
//    /* 定时器 0 中断使能*/
//    timer0_int_set(p_tmr0_x, channel, 1);
//    /* 等待至少3个异步时钟周期*/
//    delay_ms(1);
//    /* 设置内部硬件捕获源*/
//    timer0_trigger_src_set(EVT_PORT_EIRQ0);
//
//    return 0;
//}


